import { rotateY } from "gl-matrix-ts/dist/mat4";
import { Matrix4 } from "../../utils/Matrix4";
import { MatrixStack } from "../../utils/MatrixStack";
import { TextrueUtil } from "../../utils/TextureUtil";
import { Util } from "../../utils/Util";
import { WebGLUtil } from "../../utils/WebGLUtil";
import { Render } from "../Render";
import { WebglTemplateBase } from "../template/WebglTemplateBase";

/*
 * @Author: Snow
 * @Date: 2021-10-18 17:36:28
 * @Description: 矩阵栈 
 */
export class TextureMatrixStack1 extends WebglTemplateBase {
    protected override initProgram(): void {
        this.vsSource = `
            attribute vec4 a_position;
            attribute vec2 a_texcoord;
            
            uniform mat4 u_matrix;
            
            varying vec2 v_texcoord;
            
            void main() {
                // Multiply the position by the matrix.
                gl_Position = u_matrix * a_position;
                v_texcoord = a_texcoord;
            }
        `;

        this.fsSource = `
            precision mediump float;

            // Passed in from the vertex shader.
            varying vec2 v_texcoord;
            
            // The texture.
            uniform sampler2D u_texture;
            
            void main() {
                gl_FragColor = texture2D(u_texture, v_texcoord);
            }
        `;
        super.initProgram();
    }

    protected override initBuffers(): void {
        super.initBuffers();
        const gl = Render.GL;

        var positions = [
            0, 0,
            0, 1,
            1, 0,
            1, 0,
            0, 1,
            1, 1,
        ];

        let texcoords = [
            0, 0,
            0, 1,
            1, 0,
            1, 0,
            0, 1,
            1, 1,
        ];


        // an indexed quad
        let arrays = {
            position: { numComponents: 2, data: positions, },
            texcoord: { numComponents: 2, data: texcoords, },
        };


        let bufferInfo = WebGLUtil.createBufferInfoFromArrays(gl, arrays);
        let speed = 1;
        let textureInfos = [
            this.loadImageAndCreateTextureInfo('star.jpg'),
            this.loadImageAndCreateTextureInfo('leaves.jpg'),
            this.loadImageAndCreateTextureInfo('keyboard.jpg'),
        ];

        let nodeInfo:{
            textureInfo:{
                width: number,   // 图像加载前不知道大小
                height: number,
                texture: WebGLTexture,
            },
            dy:number,
            dx:number,
            x:number,
            y:number
        }

        let nodeInfos = [];
        let num = 10;
        for (let index = 0; index < num; index++) {
            const texInfo = textureInfos[Util.randInt(3)];
            let node = {
                textureInfo:texInfo,
                x:Math.random() * gl.canvas.width,
                y:Math.random() * gl.canvas.height,
                dx:Math.random() > 0.1?1:-1,
                dy:Math.random() > 0.1?1:-1,
            }
            nodeInfos.push(node);
        }

        let matrixStack = new MatrixStack();

        
        let drawScene = () => {
            let time = this.ts;
            time = time;
            WebGLUtil.resizeCanvasToMatchDisplaySize(gl);
            // Clear the canvas AND the depth buffer.
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

            matrixStack.save();
            matrixStack.translate(gl.canvas.width / 2,gl.canvas.height / 2);
            matrixStack.rotateZ(time);
            matrixStack.translate(-textureInfos[0].width/2,-textureInfos[0].height/2);
            
            drawImage(textureInfos[0].texture,textureInfos[0].width,textureInfos[0].height,0,0);

            matrixStack.restore();
            // for (let index = 0; index < nodeInfos.length; index++) {
            //     const element = nodeInfos[index];
            //     let x:number = element.x;
            //     let y:number = element.y;
            //     x += speed * element.dx;
            //     y += speed * element.dy;
            //     let textureInfo = element.textureInfo as {
            //         width: number,   // 图像加载前不知道大小
            //         height: number,
            //         texture: WebGLTexture,
            //     };
            //     if(x > gl.canvas.width){
            //         element.dx = -1;
            //     }
            //     if(y > gl.canvas.height){
            //         element.dy = -1;
            //     }
            //     if(x < 0){
            //         element.dx = 1;
            //     }
            //     if(y < 0){
            //         element.dy = 1;
            //     }

            //     element.x = x;
            //     element.y = y;
            //     //element.disX = 10;
            //     //element.disY = 10;
            //     drawImage(textureInfo.texture,textureInfo.width,textureInfo.height,element.x,element.y);
            // }
            
        }

        let drawImage = (tex: WebGLTexture, texWidth: number, texHeight: number, disX: number, disY: number) => {
            gl.bindTexture(gl.TEXTURE_2D, tex);
            gl.useProgram(this.programInfo.program);

            let matrix = Matrix4.orthographic(0, gl.canvas.width, gl.canvas.height, 0, -1, 1);
            // 将原点移动到栈顶矩阵代表的转换
            matrix = Matrix4.multiply(matrix, matrixStack.getCurrentMatrix());
            matrix = Matrix4.multiply(matrix, Matrix4.translation(disX, disY, 0))
            matrix = Matrix4.multiply(matrix, Matrix4.scaling(texWidth, texHeight, 1));

            let texUnforms = {
                u_texture: tex,
                u_matrix: matrix
            }

            // Setup all the needed buffers and attributes.
            WebGLUtil.setBuffersAndAttributes(gl, this.programInfo, bufferInfo);

            // Set the uniforms that are the same for all objects.
            WebGLUtil.setUniforms(this.programInfo, texUnforms);

            // Draw the geometry.
            gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numElements);

        }
        this.draw = drawScene;
    }

    // 穿件一个纹理信息 { width: w, height: h, texture: tex }
    // 纹理起初为 1x1 像素，当图像加载完成后更新大小
    public loadImageAndCreateTextureInfo(url: string): {
        width: number,   // 图像加载前不知道大小
        height: number,
        texture: WebGLTexture,
    } {
        const gl = Render.GL;
        let tex = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, tex);

        // 假设所有的图像维度都不是2的整数次幂
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

        let textureInfo = {
            width: 1,   // 图像加载前不知道大小
            height: 1,
            texture: tex,
        };
        let img = new Image();
        img.addEventListener('load',  ()=> {
            textureInfo.width = img.width;
            textureInfo.height = img.height;
            gl.bindTexture(gl.TEXTURE_2D, textureInfo.texture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
        });
        img.src = url;
        return textureInfo;
    }
}